package cumeo89.chii.client.entry;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.xml.client.Attr;
import com.google.gwt.xml.client.Document;
import com.google.gwt.xml.client.Element;
import com.google.gwt.xml.client.Node;

public class EntryModel {

	private List<EntryModelListener> listeners = new ArrayList<EntryModelListener>();

	private Document document;

	public EntryModel() {
	}

	public Document getDocument() {
		return document;
	}

	public void setDocument(Document doc) {
		this.document = doc;
		for (EntryModelListener lis : listeners) {
			lis.documentUpdated(this);
		}
	}

	public String getTitle() {
		return getDocument().getDocumentElement().getAttribute(
				Constants.A_ENTRY_TITLE);
	}

	public void appendChild(Node parent, Node newChild) {
		insertBefore(parent, newChild, null);
	}

	public void insertBefore(Node parent, Node newChild, Node before) {
		parent.insertBefore(newChild, before);
		fireNodeInserted(newChild);
	}

	public void remove(Node child) {
		Node parent = child.getParentNode(), refChild = child.getNextSibling();
		parent.removeChild(child);
		fireNodeRemoved(child, parent, refChild);
	}

	public void setValue(Node node, String value) {
		String oldValue = node.getNodeValue();
		node.setNodeValue(value);
		fireNodeUpdated(node, oldValue);
	}

	public void setAttribute(Element element, String name, String value) {
		if (value == null) {
			Attr attr = element.getAttributeNode(name);
			element.removeAttribute(name);
			fireAttrRemoved(element, attr);
		} else {
			String oldValue = element.getAttribute(name);
			element.setAttribute(name, value);
			Attr attr = element.getAttributeNode(name);
			fireAttrSetted(element, attr, oldValue);
		}
	}

	private void fireNodeInserted(Node newChild) {
		for (EntryModelListener lis : listeners) {
			lis.nodeInserted(this, newChild);
		}
	}

	private void fireNodeUpdated(Node node, String oldValue) {
		for (EntryModelListener lis : listeners) {
			lis.nodeUpdated(this, node, oldValue);
		}
	}

	private void fireNodeRemoved(Node child, Node parent, Node refChild) {
		for (EntryModelListener lis : listeners) {
			lis.nodeRemoved(this, child, parent, refChild);
		}
	}

	private void fireAttrSetted(Element element, Attr attr, String oldValue) {
		for (EntryModelListener lis : listeners) {
			lis.attrSetted(this, element, attr, oldValue);
		}
	}

	private void fireAttrRemoved(Element element, Attr attr) {
		for (EntryModelListener lis : listeners) {
			lis.attrRemoved(this, element, attr);
		}
	}

	public void addEntryModelListener(EntryModelListener l) {
		if (listeners.contains(l)) {
			return;
		}
		listeners.add(l);
	}

	public void removeEntryModelListener(EntryModelListener l) {
		listeners.remove(l);
	}

}